package com.rede.didiok.sms.event;

import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.rede.didiok.common.constant.conf.RedisConf;
import com.rede.didiok.common.constant.global.Constants;
import com.rede.didiok.common.domainEvent.DomainEvent;
import com.rede.didiok.common.domainEvent.EntityType;
import com.rede.didiok.common.dto.community.CommunityPraiseRecordDto;
import com.rede.didiok.common.enums.NoticeTypeEnum;
import com.rede.didiok.common.enums.ResourceTypeEnum;
import com.rede.didiok.common.enums.WebDomainEventEnum;
import com.rede.didiok.common.exception.exceptionType.FeignException;
import com.rede.didiok.common.feign.WebFeignClient;
import com.rede.didiok.common.utils.R;
import com.rede.didiok.common.utils.StringUtils;
import com.rede.didiok.sms.event.annotation.EventType;
import com.rede.didiok.sms.event.service.AbstractEventHandler;
import com.rede.didiok.sms.task.enums.Action;

/**
 * 点赞事件处理器
 */
@Slf4j
@Component
@EventType({EntityType.COMMUNITY_PRAISE})
public class CommunityPraiseEventHandler extends AbstractEventHandler {
    @Resource
    private WebFeignClient webFeignClient;
    @Override
    public void doEventHandler(DomainEvent domainEvent) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        CommunityPraiseRecordDto communityPraiseRecordDto = objectMapper.convertValue(domainEvent.getEntity(), CommunityPraiseRecordDto.class);
        switch (domainEvent.getEventAction()) {
            case COMMUNITY_PRAISE_ADD: {
                this.addPraise(communityPraiseRecordDto);
            }
            break;
            case COMMUNITY_PRAISE_CANCEL: {
                this.cancelPraise(communityPraiseRecordDto);
            }
            break;
            case COMMUNITY_TREAD_ADD: {
                this.addTread(communityPraiseRecordDto);
            }
            break;
            case COMMUNITY_TREAD_CANCEL: {
                this.cancelTrade(communityPraiseRecordDto);
            }
            break;
        }
    }

    /**
     * 添加点赞
     *
     * @param communityPraiseRecordDto
     */
    public void addPraise(CommunityPraiseRecordDto communityPraiseRecordDto) {
        /**
         * 站内信通知
         */
        // 类型校验
        ResourceTypeEnum resourceType = ResourceTypeEnum.getType(communityPraiseRecordDto.getResourceType());
        String toUserUid = commonManager.getUserUidByResource(resourceType, communityPraiseRecordDto.getResourceUid());
        if (StringUtils.isNotEmpty(toUserUid)) {
            // 给对方收件箱发消息
            // 给该资源的用户发送点赞通知
            asyncService.executeAsyncNotice(toUserUid, NoticeTypeEnum.PRAISE, ResourceTypeEnum.resourceType2BusinessType(resourceType, 1), communityPraiseRecordDto.getUid());
            // 同时向作者插入一条小红点
            String redisKey = RedisConf.USER_RECEIVE_PRAISE_COUNT + Constants.SYMBOL_COLON + toUserUid;
            String watchCount = redisUtil.get(redisKey);
            if (StringUtils.isNotEmpty(watchCount)) {
                redisUtil.incrBy(redisKey, Constants.NUM_ONE);
            } else {
                redisUtil.setEx(redisKey, Constants.STR_ONE, 7, TimeUnit.DAYS);
            }
            // 刷新通知
            webFeignClient.sendDomainEventMessage(WebDomainEventEnum.NOTICE_FLUSH, toUserUid);
        }

        // 更新被点赞/点踩的用户uid
        communityPraiseRecordDto.setToUserUid(toUserUid);
        R praiseRecordResult = communityFeignClient.updatePraiseRecordById(communityPraiseRecordDto);

        if (praiseRecordResult.getCode() != 0) {
            // 获取异常信息
            throw new FeignException("feign调用异常（根据id更新点赞）：失败啦");
        }

        // 更新用户点赞缓存
        this.deleteUserPraiseCache(communityPraiseRecordDto);

        // 任务执行
        userTaskService.action(Action.COMMUNITY_PRAISE, null, null);

        // 执行被点赞方的任务
        userTaskService.action(Action.TO_COMMUNITY_PRAISE, null, null, communityPraiseRecordDto.getToUserUid());
    }

    /**
     * 添加点踩
     *
     * @param userPraiseRecord
     */
    public void addTread(CommunityPraiseRecordDto userPraiseRecord) {
        this.deleteUserPraiseCache(userPraiseRecord);
    }

    /**
     * 取消点赞
     *
     * @param userPraiseRecord
     */
    public void cancelPraise(CommunityPraiseRecordDto userPraiseRecord) {
        this.deleteUserPraiseCache(userPraiseRecord);
    }

    /**
     * 取消点踩
     *
     * @param userPraiseRecord
     */
    public void cancelTrade(CommunityPraiseRecordDto userPraiseRecord) {
        this.deleteUserPraiseCache(userPraiseRecord);
    }

    /**
     * 清空缓存
     *
     * @param userPraiseRecord
     */
    private void deleteUserPraiseCache(CommunityPraiseRecordDto userPraiseRecord) {
        // 缓存资源id的点赞数、点踩数
        redisUtil.delete(RedisConf.COMMUNITY_TREAD_COUNT + RedisConf.SEGMENTATION + userPraiseRecord.getResourceUid());
        redisUtil.delete(RedisConf.IS_USER_COMMUNITY_TREAD + RedisConf.SEGMENTATION + userPraiseRecord.getCreateUserUid() + RedisConf.SEGMENTATION + userPraiseRecord.getResourceUid());
    }
}
